/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.cabs.jpa.control;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.cabs.entity.Account;
import org.cabs.entity.Role;
import org.cabs.entity.Payment;
import org.cabs.entity.Enquiry;
import java.util.ArrayList;
import java.util.Collection;
import org.cabs.entity.Company;
import org.cabs.entity.Driver;
import org.cabs.jpa.control.exceptions.IllegalOrphanException;
import org.cabs.jpa.control.exceptions.NonexistentEntityException;
import org.cabs.jpa.control.exceptions.PreexistingEntityException;

/**
 *
 * @author HaoPT
 */
public class AccountJpaController {

    public AccountJpaController() {
        emf = Persistence.createEntityManagerFactory("RadioCabsPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Account account) throws PreexistingEntityException, Exception {
        if (account.getEnquiryCollection() == null) {
            account.setEnquiryCollection(new ArrayList<Enquiry>());
        }
        if (account.getCompanyCollection() == null) {
            account.setCompanyCollection(new ArrayList<Company>());
        }
        if (account.getDriverCollection() == null) {
            account.setDriverCollection(new ArrayList<Driver>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Role roleId = account.getRoleId();
            if (roleId != null) {
                roleId = em.getReference(roleId.getClass(), roleId.getId());
                account.setRoleId(roleId);
            }
            Payment paymentId = account.getPaymentId();
            if (paymentId != null) {
                paymentId = em.getReference(paymentId.getClass(), paymentId.getId());
                account.setPaymentId(paymentId);
            }
            Collection<Enquiry> attachedEnquiryCollection = new ArrayList<Enquiry>();
            for (Enquiry enquiryCollectionEnquiryToAttach : account.getEnquiryCollection()) {
                enquiryCollectionEnquiryToAttach = em.getReference(enquiryCollectionEnquiryToAttach.getClass(), enquiryCollectionEnquiryToAttach.getId());
                attachedEnquiryCollection.add(enquiryCollectionEnquiryToAttach);
            }
            account.setEnquiryCollection(attachedEnquiryCollection);
            Collection<Company> attachedCompanyCollection = new ArrayList<Company>();
            for (Company companyCollectionCompanyToAttach : account.getCompanyCollection()) {
                companyCollectionCompanyToAttach = em.getReference(companyCollectionCompanyToAttach.getClass(), companyCollectionCompanyToAttach.getId());
                attachedCompanyCollection.add(companyCollectionCompanyToAttach);
            }
            account.setCompanyCollection(attachedCompanyCollection);
            Collection<Driver> attachedDriverCollection = new ArrayList<Driver>();
            for (Driver driverCollectionDriverToAttach : account.getDriverCollection()) {
                driverCollectionDriverToAttach = em.getReference(driverCollectionDriverToAttach.getClass(), driverCollectionDriverToAttach.getId());
                attachedDriverCollection.add(driverCollectionDriverToAttach);
            }
            account.setDriverCollection(attachedDriverCollection);
            em.persist(account);
            if (roleId != null) {
                roleId.getAccountCollection().add(account);
                roleId = em.merge(roleId);
            }
            if (paymentId != null) {
                paymentId.getAccountCollection().add(account);
                paymentId = em.merge(paymentId);
            }
            for (Enquiry enquiryCollectionEnquiry : account.getEnquiryCollection()) {
                Account oldIdAccountOfEnquiryCollectionEnquiry = enquiryCollectionEnquiry.getIdAccount();
                enquiryCollectionEnquiry.setIdAccount(account);
                enquiryCollectionEnquiry = em.merge(enquiryCollectionEnquiry);
                if (oldIdAccountOfEnquiryCollectionEnquiry != null) {
                    oldIdAccountOfEnquiryCollectionEnquiry.getEnquiryCollection().remove(enquiryCollectionEnquiry);
                    oldIdAccountOfEnquiryCollectionEnquiry = em.merge(oldIdAccountOfEnquiryCollectionEnquiry);
                }
            }
            for (Company companyCollectionCompany : account.getCompanyCollection()) {
                Account oldIdAccountOfCompanyCollectionCompany = companyCollectionCompany.getIdAccount();
                companyCollectionCompany.setIdAccount(account);
                companyCollectionCompany = em.merge(companyCollectionCompany);
                if (oldIdAccountOfCompanyCollectionCompany != null) {
                    oldIdAccountOfCompanyCollectionCompany.getCompanyCollection().remove(companyCollectionCompany);
                    oldIdAccountOfCompanyCollectionCompany = em.merge(oldIdAccountOfCompanyCollectionCompany);
                }
            }
            for (Driver driverCollectionDriver : account.getDriverCollection()) {
                Account oldIdAccountOfDriverCollectionDriver = driverCollectionDriver.getIdAccount();
                driverCollectionDriver.setIdAccount(account);
                driverCollectionDriver = em.merge(driverCollectionDriver);
                if (oldIdAccountOfDriverCollectionDriver != null) {
                    oldIdAccountOfDriverCollectionDriver.getDriverCollection().remove(driverCollectionDriver);
                    oldIdAccountOfDriverCollectionDriver = em.merge(oldIdAccountOfDriverCollectionDriver);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findAccount(account.getId()) != null) {
                throw new PreexistingEntityException("Account " + account + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Account account) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Account persistentAccount = em.find(Account.class, account.getId());
            Role roleIdOld = persistentAccount.getRoleId();
            Role roleIdNew = account.getRoleId();
            Payment paymentIdOld = persistentAccount.getPaymentId();
            Payment paymentIdNew = account.getPaymentId();
            Collection<Enquiry> enquiryCollectionOld = persistentAccount.getEnquiryCollection();
            Collection<Enquiry> enquiryCollectionNew = account.getEnquiryCollection();
            Collection<Company> companyCollectionOld = persistentAccount.getCompanyCollection();
            Collection<Company> companyCollectionNew = account.getCompanyCollection();
            Collection<Driver> driverCollectionOld = persistentAccount.getDriverCollection();
            Collection<Driver> driverCollectionNew = account.getDriverCollection();
            List<String> illegalOrphanMessages = null;
            for (Enquiry enquiryCollectionOldEnquiry : enquiryCollectionOld) {
                if (!enquiryCollectionNew.contains(enquiryCollectionOldEnquiry)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Enquiry " + enquiryCollectionOldEnquiry + " since its idAccount field is not nullable.");
                }
            }
            for (Company companyCollectionOldCompany : companyCollectionOld) {
                if (!companyCollectionNew.contains(companyCollectionOldCompany)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Company " + companyCollectionOldCompany + " since its idAccount field is not nullable.");
                }
            }
            for (Driver driverCollectionOldDriver : driverCollectionOld) {
                if (!driverCollectionNew.contains(driverCollectionOldDriver)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Driver " + driverCollectionOldDriver + " since its idAccount field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (roleIdNew != null) {
                roleIdNew = em.getReference(roleIdNew.getClass(), roleIdNew.getId());
                account.setRoleId(roleIdNew);
            }
            if (paymentIdNew != null) {
                paymentIdNew = em.getReference(paymentIdNew.getClass(), paymentIdNew.getId());
                account.setPaymentId(paymentIdNew);
            }
            Collection<Enquiry> attachedEnquiryCollectionNew = new ArrayList<Enquiry>();
            for (Enquiry enquiryCollectionNewEnquiryToAttach : enquiryCollectionNew) {
                enquiryCollectionNewEnquiryToAttach = em.getReference(enquiryCollectionNewEnquiryToAttach.getClass(), enquiryCollectionNewEnquiryToAttach.getId());
                attachedEnquiryCollectionNew.add(enquiryCollectionNewEnquiryToAttach);
            }
            enquiryCollectionNew = attachedEnquiryCollectionNew;
            account.setEnquiryCollection(enquiryCollectionNew);
            Collection<Company> attachedCompanyCollectionNew = new ArrayList<Company>();
            for (Company companyCollectionNewCompanyToAttach : companyCollectionNew) {
                companyCollectionNewCompanyToAttach = em.getReference(companyCollectionNewCompanyToAttach.getClass(), companyCollectionNewCompanyToAttach.getId());
                attachedCompanyCollectionNew.add(companyCollectionNewCompanyToAttach);
            }
            companyCollectionNew = attachedCompanyCollectionNew;
            account.setCompanyCollection(companyCollectionNew);
            Collection<Driver> attachedDriverCollectionNew = new ArrayList<Driver>();
            for (Driver driverCollectionNewDriverToAttach : driverCollectionNew) {
                driverCollectionNewDriverToAttach = em.getReference(driverCollectionNewDriverToAttach.getClass(), driverCollectionNewDriverToAttach.getId());
                attachedDriverCollectionNew.add(driverCollectionNewDriverToAttach);
            }
            driverCollectionNew = attachedDriverCollectionNew;
            account.setDriverCollection(driverCollectionNew);
            account = em.merge(account);
            if (roleIdOld != null && !roleIdOld.equals(roleIdNew)) {
                roleIdOld.getAccountCollection().remove(account);
                roleIdOld = em.merge(roleIdOld);
            }
            if (roleIdNew != null && !roleIdNew.equals(roleIdOld)) {
                roleIdNew.getAccountCollection().add(account);
                roleIdNew = em.merge(roleIdNew);
            }
            if (paymentIdOld != null && !paymentIdOld.equals(paymentIdNew)) {
                paymentIdOld.getAccountCollection().remove(account);
                paymentIdOld = em.merge(paymentIdOld);
            }
            if (paymentIdNew != null && !paymentIdNew.equals(paymentIdOld)) {
                paymentIdNew.getAccountCollection().add(account);
                paymentIdNew = em.merge(paymentIdNew);
            }
            for (Enquiry enquiryCollectionNewEnquiry : enquiryCollectionNew) {
                if (!enquiryCollectionOld.contains(enquiryCollectionNewEnquiry)) {
                    Account oldIdAccountOfEnquiryCollectionNewEnquiry = enquiryCollectionNewEnquiry.getIdAccount();
                    enquiryCollectionNewEnquiry.setIdAccount(account);
                    enquiryCollectionNewEnquiry = em.merge(enquiryCollectionNewEnquiry);
                    if (oldIdAccountOfEnquiryCollectionNewEnquiry != null && !oldIdAccountOfEnquiryCollectionNewEnquiry.equals(account)) {
                        oldIdAccountOfEnquiryCollectionNewEnquiry.getEnquiryCollection().remove(enquiryCollectionNewEnquiry);
                        oldIdAccountOfEnquiryCollectionNewEnquiry = em.merge(oldIdAccountOfEnquiryCollectionNewEnquiry);
                    }
                }
            }
            for (Company companyCollectionNewCompany : companyCollectionNew) {
                if (!companyCollectionOld.contains(companyCollectionNewCompany)) {
                    Account oldIdAccountOfCompanyCollectionNewCompany = companyCollectionNewCompany.getIdAccount();
                    companyCollectionNewCompany.setIdAccount(account);
                    companyCollectionNewCompany = em.merge(companyCollectionNewCompany);
                    if (oldIdAccountOfCompanyCollectionNewCompany != null && !oldIdAccountOfCompanyCollectionNewCompany.equals(account)) {
                        oldIdAccountOfCompanyCollectionNewCompany.getCompanyCollection().remove(companyCollectionNewCompany);
                        oldIdAccountOfCompanyCollectionNewCompany = em.merge(oldIdAccountOfCompanyCollectionNewCompany);
                    }
                }
            }
            for (Driver driverCollectionNewDriver : driverCollectionNew) {
                if (!driverCollectionOld.contains(driverCollectionNewDriver)) {
                    Account oldIdAccountOfDriverCollectionNewDriver = driverCollectionNewDriver.getIdAccount();
                    driverCollectionNewDriver.setIdAccount(account);
                    driverCollectionNewDriver = em.merge(driverCollectionNewDriver);
                    if (oldIdAccountOfDriverCollectionNewDriver != null && !oldIdAccountOfDriverCollectionNewDriver.equals(account)) {
                        oldIdAccountOfDriverCollectionNewDriver.getDriverCollection().remove(driverCollectionNewDriver);
                        oldIdAccountOfDriverCollectionNewDriver = em.merge(oldIdAccountOfDriverCollectionNewDriver);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = account.getId();
                if (findAccount(id) == null) {
                    throw new NonexistentEntityException("The account with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Account account;
            try {
                account = em.getReference(Account.class, id);
                account.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The account with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Collection<Enquiry> enquiryCollectionOrphanCheck = account.getEnquiryCollection();
            for (Enquiry enquiryCollectionOrphanCheckEnquiry : enquiryCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Account (" + account + ") cannot be destroyed since the Enquiry " + enquiryCollectionOrphanCheckEnquiry + " in its enquiryCollection field has a non-nullable idAccount field.");
            }
            Collection<Company> companyCollectionOrphanCheck = account.getCompanyCollection();
            for (Company companyCollectionOrphanCheckCompany : companyCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Account (" + account + ") cannot be destroyed since the Company " + companyCollectionOrphanCheckCompany + " in its companyCollection field has a non-nullable idAccount field.");
            }
            Collection<Driver> driverCollectionOrphanCheck = account.getDriverCollection();
            for (Driver driverCollectionOrphanCheckDriver : driverCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Account (" + account + ") cannot be destroyed since the Driver " + driverCollectionOrphanCheckDriver + " in its driverCollection field has a non-nullable idAccount field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Role roleId = account.getRoleId();
            if (roleId != null) {
                roleId.getAccountCollection().remove(account);
                roleId = em.merge(roleId);
            }
            Payment paymentId = account.getPaymentId();
            if (paymentId != null) {
                paymentId.getAccountCollection().remove(account);
                paymentId = em.merge(paymentId);
            }
            em.remove(account);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Account> findAccountEntities() {
        return findAccountEntities(true, -1, -1);
    }

    public List<Account> findAccountEntities(int maxResults, int firstResult) {
        return findAccountEntities(false, maxResults, firstResult);
    }

    private List<Account> findAccountEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Account.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Account findAccount(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Account.class, id);
        } finally {
            em.close();
        }
    }

    public int getAccountCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Account> rt = cq.from(Account.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
